本系列文章已出版實體書籍:
「你的地圖會說話?WebGIS 與 JavaScript 的情感交織」(博碩文化)
WebGIS啟蒙首選✖五家地圖API✖近百個程式範例✖實用簡易口訣✖學習難度分級✖補充ES6小知識
今天要來跟大家介紹環域查詢的前置作業。
使用者在圖台網站上想要查詢一塊區域內的資料,首先,
要先決定查詢的範圍可能是圓、長方形、不規則多邊形等等,
有兩種方式。
今天我們就要來使用Leaflet API來實現繪圖工具。
很久沒使用leaflet了,來幫大家複習一下。
↓ 先引入圖台基本的css與js
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
↓ 建一個存放地圖的div
    <div id="lmap"></div>
↓ 今天附上簡易的css,存放地圖div的高度記得要設定,不然地圖會顯現不出來!
        #lmap {
            height: 100%;
        }
        html,
        body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
↓ 初始化地圖
        var LMap = L.map(document.getElementById('lmap'), {
            center: [23.5, 121],  // 中心點
            zoom: 7,  // 縮放層級
            crs: L.CRS.EPSG3857,  // 座標系統
        });
        L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
            maxZoom: 18,
            id: 'mapbox.streets'
        }).addTo(LMap);  // 新增底圖
Leaflet API有一個很不錯的繪圖工具,繪圖完成後可以直接畫好在地圖上,並且可以儲存、編輯、返回上一個繪圖動作。

↑ 繪圖工具

↑ 點擊

↑ 完成

↑ 返回上一個動作
↓ 引入繪圖的css與js
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.2/leaflet.draw.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.2/leaflet.draw.js"></script>
↓ 建立一個FeatureGroup,用以存放繪圖的圖資
        var drawItem = new L.FeatureGroup();
        LMap.addLayer(drawItem);
↓ 新增繪圖的控制項
        var option = {
            position: 'topleft',
            collapsed: true,
            edit: {
                featureGroup: drawItem,
            },
        };
        var drawControl = new L.Control.Draw(option);
        LMap.addControl(drawControl);
↓ 新增繪圖的事件,在繪圖建立完的時候發生的callback function。
        LMap.on(L.Draw.Event.CREATED, function (e) {
             var layer = e.layer;
             drawItem.addLayer(layer);  // 必須將畫完的圖層加入
             console.log(arguments);
        });
        
        // 另一種寫法,以字串的方式寫事件名稱
        LMap.on('draw:created', function (e) {
             var layer = e.layer;
             console.log(arguments);
             drawItem.addLayer(layer);            
        });
↓ Leaflet 繪圖事件一覽
↓ 讓我們來看看繪圖建立完成的callback function的arguments
↓ 可以找到layer,並利用layer的方法找到繪製的半徑與中心點座標。並用layerType判斷圖形是哪一種形狀。
        LMap.on(L.Draw.Event.CREATED, function (e) {
            var layer = e.layer;
            var type = e.layerType;
            drawItem.addLayer(layer);
            console.log(type);
            if (type === 'circle') {
                var center = layer.getLatLng();
                var radius = layer.getRadius();
                console.log(`經度: ${center.lng}, 緯度: ${center.lat}`);
                console.log(`半徑: ${radius} (m)`);
            }
        });
↓ 結果
↓ 如果今天針對不同種圖形,要做相對應的事情,就要用if...else...來判斷type
            if (type === 'circle') {
                var center = layer.getLatLng();
                var radius = layer.getRadius();
                console.log(`經度: ${center.lng}, 緯度: ${center.lat}`);
                console.log(`半徑: ${radius} (m)`);
                
            } else if (type === 'marker'){
                var point = layer.getLatLng();
                console.log(`經度: ${point.lng}, 緯度: ${point.lat}`);
                
            } else if (type === 'rectangle'){
                var str ="";
                var arr = layer.getLatLngs();
                arr = arr[0].forEach(function(item, index){
                   str += `${index} => 經度: ${item.lng}, 緯度: ${item.lat}`
                });
                console.log(str);
            } else if (type === 'polygon'){
                var str ="";
                var arr = layer.getLatLngs();
                arr = arr[0].map(function(item, index){
                   return{
                       x: item.lng,
                       y: item.lat
                   }
                });
                console.log(arr);
            }
if...else...越寫越長,越寫越多,越寫越不直觀。有沒有什麼方法?在不寫if...else...的情況下來因應不同種的情形,不但不寫判斷,還要讓每一個function獨立只作業一件事情。
下一篇及下下篇,要來跟大家介紹callback與promise,
並且用adapter design pattern(配接器)的設計模式,
來重新寫callback function!
並達到最簡化判斷式的效果。
最近每天上班寫程式處理雜事,下班寫程式寫文章,腦袋越來越容易打結QAQ![]()